package raytracer.main;

import raytracer.math.Color3d;
import raytracer.math.Vector3d;
import raytracer.misc.Material;
import raytracer.misc.Camera;
import raytracer.objects.*;
import raytracer.misc.*;

/**
 * @todo for uniform grid:
 *  	 do something about the ambient occlusion inner transparency
 * @todo maybe add some uniform or statistical distribution for AO samples
 * @todo separate display and raytracing
 * @todo don't weight reflection intensity with phong model
 * @todo shadow transparency: consider light source's color?
 * @todo add more primitives :P
 * @todo transparency and intersecting solid objects :S
 * @todo fresnel?
 * @todo maybe separate calculation of normals and intersection
 *  
 * * Changelog:
 *  - Also changed the shadowRay intersection (shadow color now just considers
 *    the nearest object's transparency - maybe fix that in future version?)
 *  - Changed most intersections to call the uniform grid instead of all objects
 *  - Added UniformGrid
 *  - Added BoundingBox class for usage in the uniform grid
 *  - Added method for asking objects if they are infinite (e.g. planes)
 *  - Added triggers for phong shading, reflections and transparency (which made some code-changes necessary)
 *  - Added configuration constants for disabling shadows and AO in raytracer.misc.AppWideConstants
 *  - Moved some constants to raytracer.misc.AppWideConstants for global access (e.g. EPSILON)
 *  - Yeeeeeeeeehaaaaaaa...added Ambient Occlusion :D
 *  - Image is now just displayed when rendering has finished..progess display has been added
 *  - Implemented some really basic OBJ-Reader
 *  - Fixed some issues with the shadows of transparent objects
 *  - Corrected reflection routine (used absolute position of ray's origin instead of direction)
 *  - Added code in Raytracer.java to make planes and triangles lightened from the correct side
 *  - Implemented Triangles with barycentrical intersection method
 *  - Removed redundant calculation of LightPointer (same as shadowray)
 *  - Fixed a problem with shadow colors where just one blocked light source resulted in a totally black shadow
 *  - Added strange AntiAliasing (just scaling down the picture.. ;))
 *  - The Raytracer now just returns the rendering time instead of printing it to the console
 *  - Made it possible to call the intersect-method with null-values for intersection point and normal
 *  - added blocker cache
 *  - the image is now repainted just every line, not every pixel (massive speed-up :P)
 *  - separated raytracing logic from scene generation
 *  - Created own Vector3d and Color3d classes (independence for tibet :S)
 *  - Implemented BufferedImage for displaying the rendered picture
 *  - Changed from usage of graphics2d and fillRect to the direct
 *    use of setRGB on the output Image
 * @author Thorsten Roth
 * @version 04.11.2006
 */
public class RTMain {

	private static Raytracer raytracer;
	
	private static Scene generateScene() {
		Camera cam=new Camera(
				new Vector3d(20,20,25),	//campos
				new Vector3d(0,1,0),	//upvector
				new Vector3d(7,9,7),	//vpc
				Math.toRadians(24),		//hfov
				Math.toRadians(24)		//vfov
		);
		
		
		Scene s=new Scene(cam);
						
		Plane plane=new Plane(new Vector3d(0,1,0),0);
		Material m=new Material();
//		m.setDiffuseColor(new Color3d(.5,1,.5));
//		m.setSpecularColor(new Color3d(.5,1,.5));
//		m.setLocalColor(new Color3d(1,1,1));
//		m.setKLocal(0);
//		m.setKReflective(0);
//		m.setKDiffuse(1);
//		m.setKSpecular(0);
//		m.setRefrIndex(1.2f);
//		m.normalize();
//		plane.setMaterial(m);
//		s.addObject(plane);
		
		m=new Material();
		m.setLocalColor(new Color3d(0,1,0));
		m.setDiffuseColor(new Color3d(.98,.98,1));
		m.setSpecularColor(new Color3d(1,1,1));
		m.setKReflective(0);
		m.setKLocal(0);
		m.setKDiffuse(1);
		m.setKSpecular(0);
		m.setRefrIndex(1);
		m.setKTransparent(0);
		m.normalize();
					
		ObjReader objReader=new ObjReader("cube.obj");
		for (Triangle t:objReader.getTriangles()) {
			t.setMaterial(m);
			s.addObject(t);
		}
		
		m=new Material(m);
		m.setKTransparent(0);
		m.setRefrIndex(1.1f);
		m.setDiffuseColor(new Color3d(1,0,0));
		m.setLocalColor(new Color3d(1,.1,.1));
		m.setKLocal(0);
		m.setKReflective(1);
		m.setKSpecular(.8f);
		m.setSpecPower(90);
		Sphere sphere=new Sphere(new Vector3d(5,14.5,5),3.5);
		sphere.setMaterial(m);
		s.addObject(sphere);
				
		/* Some random lights ... */
		for (int i=0;i<1;i++) {
			PointLight pLight=new PointLight(
					new Vector3d(50,30,20),
					new Color3d(1,1,1)
			);
			pLight.setIntensity(1);
			s.addLight(pLight);
		}
		
		return s;
	}
	
	public static void main(String[] args) {
		Scene theScene=generateScene();
		raytracer=new Raytracer(theScene);
		raytracer.setResolution(1000,1000);
		raytracer.tracePicture();
	}
	
}